package com.winner.data.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.excel.util.ListUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.winner.data.annotation.Operation;
import com.winner.data.dao.UserMapper;
import com.winner.data.entity.User;
import com.winner.data.entity.vo.UserVo;
import com.winner.data.exception.R;
import com.winner.data.service.UserService;
import com.winner.data.util.MybatisBatchUtil;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import lombok.extern.slf4j.Slf4j;

/**
 * 控制层 打印userService.getClass, 或debug查看变量userService, springboot2.0以后默认使用Cglib实现动态代理
 *
 * @RequestParam的required属性默认值是true, 你希望在请求URL中缺少某个参数时不抛出异常，可以设置 required 属性为 false
 * @RequestParam(required = false) String id
 *
 * @author wangxinle5
 * @since 2023-01-03
 */
@Slf4j
@RestController
@RequestMapping("/user")
public class UserController extends BaseController {

    UserService userService = SpringUtil.getBean(UserService.class);

    @Resource
    MessageSource messageSource;

    @Resource
    MybatisBatchUtil mybatisBatchUtil;

    @Autowired
    private JdbcTemplate jdbcTemplate;

    /**
     * localhost:8080/user/excuteSql
     *
     * @return 结果
     */
    @GetMapping("/excuteSql")
    public void excuteSql() {
        List<Map<String, Object>> maps = jdbcTemplate.queryForList("select * from user");

        // 查询list  查不到, 不会报错
        List<User> userList = jdbcTemplate.query("select * from user where id=1",
            new BeanPropertyRowMapper<>(User.class));
        System.out.println(userList.size());

        System.out.println("------------------------------------------------------");

        // 查询一个对象 查不到, 抛出EmptyResultDataAccessException异常
        User user = jdbcTemplate.queryForObject("select * from user where id=1",
            new BeanPropertyRowMapper<>(User.class));
        System.out.println(user);
    }

    /**
     * localhost:8080/user/getByList  行行比较查询list, 在没有索引的时候相比foreach or, 效率会高太多了
     *
     * @return 结果
     */
    @GetMapping("/getByList")
    public R getByList() {
        ArrayList<User> list = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            User user = new User();
            user.setName("张三");
            list.add(user);
        }
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // list大小为1000 看查询效率
        List<User> result = userService.getByList(list);
        stopWatch.stop();
        System.out.println(stopWatch.getTotalTimeSeconds());
        return success(result);
    }

    @GetMapping(value = "/getEnv")
    public R getEnv() {
        String activeProfile = SpringUtil.getActiveProfile();
        return success(activeProfile);
    }

    @GetMapping(value = "/match")
    public R match() {
        List<User> list = userService.match();
        return R.success(list);
    }

    /**
     * 分页处理 offset 自己写limit
     */
    @GetMapping(value = "/processPageByOffset")
    public void processPageByOffset() {
        userService.processPageByOffset();
    }

    /**
     * localhost:8080/user/processPageByPageNum
     * 分页处理不写sql
     */
    @GetMapping(value = "/processPageByPageNum")
    public void processPageByPageNum() {
        userService.processPageByPageNum();
    }

    /**
     * localhost:8080/user/getByPage 用mp的自定义mapper分页查询
     *
     * @return 结果
     */
    @GetMapping("/getByPage")
    public R getByPage() {
        Page<UserVo> page = userService.getByPage(1, 10);
        return success(page);
    }

    /**
     * 多语言 https://blog.csdn.net/weixin_39621870/article/details/113318919 方式一 默认不需要加配置类 请求Header添加 Accept-Language 值为
     * zh-CN 或 zh-cn 或 en-us 或 en-US
     *
     * @return 结果
     */
    @Operation(name = "zhangsan", arr = {"1", "2"})
    @GetMapping("/hello")
    public String hello() {
        return messageSource.getMessage("user.register.err.username.repeat", null, LocaleContextHolder.getLocale());
    }

    /**
     * MyBatis-Plus批量保存耗 和 MyBatis批处理功能相当, 都可以实现快速保存 并 返回主键id, 前提是数据库url &rewriteBatchedStatements=true 开启批量, 为了测试效率高,
     * 关闭mybatis日志打印 localhost:8080/user/saveBatch
     * 222
     * @return 结果
     */
    @PostMapping("/saveBatch")
    public R saveBatch() {
        //111
        List<User> list1 = ListUtils.newArrayList();
        for (int i = 0; i < 100000; i++) {
            User data = new User();
            data.setName("张三");
            list1.add(data);
        }
        StopWatch stopWatch2 = new StopWatch();
        stopWatch2.start();
        // 相比mybatisPlus的updateBatch()方法, mybatis批处理支持多个字段来更新表
        mybatisBatchUtil.batchUpdateOrInsert(list1, UserMapper.class, (item, mapper) -> mapper.insertOne(item));
        stopWatch2.stop();
        // list1.forEach(a -> System.out.println(StrUtil.format("打印批处理保存返回的主键 is {}", a.getId())));
        double totalTimeSeconds2 = stopWatch2.getTotalTimeSeconds();
        System.out.println(totalTimeSeconds2);

        List<User> list2 = ListUtils.newArrayList();
        for (int i = 0; i < 100000; i++) {
            User data = new User();
            data.setName("李四");
            list2.add(data);
        }
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        // 因为mybatisplus主键策略设置的ASSIGN_ID雪花id,那么saveBatch保存入库的就是雪花id
        userService.saveBatch(list2, 3000);
        stopWatch.stop();
        double totalTimeSeconds1 = stopWatch.getTotalTimeSeconds();
        System.out.println(totalTimeSeconds1);

        String format =
            StrUtil.format("MyBatis批处理耗时: {} 秒, MyBatis-Plus批量保存耗时: {} 秒", totalTimeSeconds1, totalTimeSeconds2);
        return success(format);

    }


    @PostMapping("/getData")
    public R saveBatch(@RequestBody User user) {
        List<User> list = ListUtils.newArrayList();
        for (int i = 0; i < 5; i++) {
            User data = new User();
            data.setName("张三");
            list.add(data);
        }
        return success(list);

    }


    /**
     * 批量删除  localhost:8080/1,2,3
     * postman的query in path 怎么写?   http://127.0.0.1/user/:ids   会自动出现在param in path
     *
     * @param ids ids
     * @return 结果
     */
    @DeleteMapping("/{ids}")
    public R checkBatchExtract(@PathVariable Long[] ids) {
        return success();
    }

}
